import { Cascader } from "antd";
import { useEffect, useState } from "react";
import { getTree, getObjectFinalValue } from "@src/tools/commonTool";

interface fieldNamesProps {
	label?: string;
	value?: string;
	children?: string;
}
export declare interface treeNodeObjProps {
	selfId: string;
	parentId: string;
}
export declare interface searchParamProps {
	paramField: string;
	optionField: string;
	defaultValue?: string | number;
}
interface CommonSearchCascaderProps {
	placeholder?: string;
	changeOnSelect?: boolean;
	searchFunc?: any;
	fieldNames?: fieldNamesProps;
	onChange?: any;
	labelInValue?: boolean;
	treeNodeObj: treeNodeObjProps;
	searchParam: searchParamProps;
	allowClear?: boolean;
	value?: any;
}

function CommonSearchCascader(props: CommonSearchCascaderProps) {
	const {
		placeholder = "请搜索",
		changeOnSelect = false,
		allowClear = false,
		searchFunc = () => {},
		fieldNames,
		onChange = () => {},
		searchParam = { paramField: "", defaultValue: "", optionField: "" },
		labelInValue = false,
		treeNodeObj = { selfId: "", parentId: "" },
	} = props;
	const [newItem, setNewItem] = useState(undefined as any);
	const [value, setValue] = useState(undefined as any);
	const [options, setOptions] = useState([]);
	const [originalOptions, setOriginalOptions] = useState([]);

	useEffect(() => {
		let obj: any = {};
		if (!!searchParam) {
			obj[searchParam.paramField] = searchParam.defaultValue;
		}
		searchFunc(obj).then((res: any) => {
			setOriginalOptions(JSON.parse(JSON.stringify(res.data)));
			const data: any = getTree(res.data, treeNodeObj);
			setOptions(data);
		});
	}, [searchFunc, treeNodeObj, searchParam]);

	useEffect(() => {
		if (!props.hasOwnProperty("value")) {
			return;
		}
		if (!!props.value && Array.isArray(props.value)) {
			setValue(props.value);
			return;
		}
		const isNew = getObjectFinalValue(props, "value.isNewItem");
		if (!!props.value && !!isNew) {
			setNewItem(props.value);
		}
	}, [props]);
	useEffect(() => {
		if (!newItem || !originalOptions.length) {
			return;
		}
		const field = getObjectFinalValue(fieldNames, "value");
		let arr: any = originalOptions.filter(
			(item) => item[field] === newItem[field]
		);
		if (!arr.length) {
			delete newItem.isNewItem;
			arr = [...originalOptions, newItem];
			setOriginalOptions(arr);
			arr = getTree(JSON.parse(JSON.stringify(arr)), treeNodeObj);
			setOptions(arr);
		}
		setValue([newItem[field]]);
		setTimeout(() => {
			setNewItem(undefined);
		}, 500);
	}, [newItem, originalOptions, treeNodeObj, fieldNames]);

	const loadData = (selectedOptions: any) => {
		const targetOption = selectedOptions[selectedOptions.length - 1];
		targetOption.loading = true;
		let params: any = {};
		params[searchParam.paramField] = targetOption[searchParam.optionField];
		searchFunc(params)
			.then((res: any) => {
				targetOption.loading = false;
				targetOption.children = res.data;
				let newOptions: any = [
					...originalOptions,
					...JSON.parse(JSON.stringify(res.data)),
				];
				setOriginalOptions(newOptions);
				setOptions([...options]);
			})
			.catch(() => {
				targetOption.loading = false;
			});
	};

	const changeSelf = (val: any) => {
		setValue(val);
		if (!val.length) {
			onChange(undefined);
		} else {
			if (labelInValue) {
				let data = originalOptions.filter(
					(item: any) =>
						item[treeNodeObj.selfId] === val[val.length - 1]
				)[0];
				onChange(data);
			} else {
				onChange(val[val.length - 1]);
			}
		}
	};
	return (
		<Cascader
			value={value}
			allowClear={allowClear}
			options={options}
			placeholder={placeholder}
			changeOnSelect={changeOnSelect}
			fieldNames={fieldNames}
			onChange={changeSelf}
			loadData={loadData}
		/>
	);
}

export default CommonSearchCascader;
